var db = require('bookshelf').bookshelf;
var Database = require('../app/database');
var Router = require('../app/router');
var moment = require('moment');
var util = require('util');

var PlayerController = module.exports = {};

log = function(msg) {
    //console.log(new Date().toLocaleTimeString() + ' [player_controller]: ' + msg);
};

PlayerController.initialize = function(router) {
	router
	.add({ Method: router.Methods.GET, URL: 'players/:id', Authorize: router.Access.Registered, Handler: PlayerController.getPlayer })
	.add({ Method: router.Methods.GET, URL: 'players', Authorize: router.Access.Registered, Handler: PlayerController.getPlayers })
	.add({ Method: router.Methods.POST, URL: 'players/bans', Authorize: router.Access.User, Handler: PlayerController.postPlayerBan })
	.add({ Method: router.Methods.POST, URL: 'players/:id/ban', Authorize: router.Access.User, Handler: PlayerController.postPlayerBan })
	.add({ Method: router.Methods.POST, URL: 'players/:id/unban', Authorize: router.Access.User, Handler: PlayerController.postPlayerUnban })
.add({ Method: router.Methods.POST, URL: 'players', Authorize: router.Access.User, Handler: PlayerController.postPlayer })
	log('initialize.js: ' + util.inspect(router,false,null));
};

PlayerController.getPlayers = function(req, res) {
    log('getPlayers: ' + req.originalUrl + ' : ' + util.inspect(req.body, { showHidden: true, depth: null }));
    log('getPlayers: ' + req.originalUrl + ' : ' + util.inspect(req.query, { showHidden: true, depth: null }));
    
    new Database.Collections.Players()
                .query(function (qb) {
                    var hasFilters = false;
                    var limit = 60;
                    if (req.query) {
                        if (req.query.is_banned != null && req.query.is_banned.length > 0) {
                            if (req.query.is_banned.toString() == "1") {
                                // TODO - Review this one, it won't work since we didn't import KNEX, but it should be possible to do it with Bookshelf.
                                qb.whereExists(function() {
                                    qb.select(Knex.raw(1))
                                    .from('bans')
                                    .whereRaw('bans.player_id = players.player_id AND bans.is_lifted = 0');
                                });
                                hasFilters = true;
                            };
                        };
                        if (req.query.last_datetime != null) {
                            if (hasFilters) {
                                qb.andWhere('last_datetime','>',moment(req.query.last_datetime).format(moment.application_dateformat));
                            } else {
                                qb.where('last_datetime','>',moment(req.query.last_datetime).format(moment.application_dateformat));
                            };
                            hasFilters = true;
                        };
                        if (req.query.server_id != null && req.query.server_id > 0) {
                            if (hasFilters) {
                                qb.andWhere('last_server',req.query.server_id);
                            } else {
                                qb.where('last_server',req.query.server_id);
                            };
                            hasFilters = true;
                        };
                        if (req.query.player_name != null && req.query.player_name.length > 0) {
                            // Lower case and trim whitespaces
                            req.query.player_name = req.query.player_name.toLowerCase().replace(/^\s\s*/, '').replace(/\s\s*$/, '');;
                            if (hasFilters) {
                                qb.andWhere('player_name','like','%' + req.query.player_name + '%');
                            } else {
                                qb.where('player_name','like','%' + req.query.player_name + '%');
                            };
                            hasFilters = true;
                        };
                        if (req.query.list_size && req.query.list_size > limit) {
                            limit = req.query.list_size;
                        };
                    };
                    qb.orderBy('last_datetime', 'desc');
                    qb.limit(limit);
		        })
                .fetch({withRelated: ['bans','bans.user']})
		        .then(function(resp) {
			        res.json(200, resp);
			        log(new Date() + ': replied: ' + util.inspect(resp,false,null));
		        });
};
PlayerController.getPlayer = function(req, res) {
	log('getPlayer: ' + req.originalUrl);
	new Database.Models.User({player_id: req.params.id})
		.fetch()
		.then(function(resp) {
			res.json(200, resp);
			log('replied: ' + util.inspect(resp,false,null));
		});
};

PlayerController.postPlayerBan = function(req, res) {
	log('postPlayerBan: ' + req.originalUrl + ' : ' + util.inspect(req.body, { showHidden: true, depth: null }));
	if (req.body) {
        var isArray = (req.body instanceof Array);
		var banArray = [].concat( req.body );
		log('banArray: ' + util.inspect(banArray,false,null));
		var isValid = true;
		var banModels = [];
        var count = 0;
        var playerIds = [];
        if (banArray != null && banArray.length > 0) {
		    for (i = 0; i < banArray.length; i++) {
                banPlayer(banArray[i], req, function(player) {
                    count++;
                    if (player != null) {
                        banModels.push(player);
                    };
                    if (isArray) {
                        if (count == banArray.length) {
                            res.send(200,banModels);
                        };
                    } else {
                        if (player != null) {
                            res.send(200,player);
                        } else {
                            res.send(500,{ status: 500, type: 'Resource', message: 'Failed to reload banned player' });
                        };
                    };
                });
		    };
        };
	} else {
		res.send(500,{ status: 500, type: 'Resource', message: 'Argument not valid' });
	};	
};

banPlayer = function(player, req, callback) {
    var playerToBan = player;
    new Database.Models.Ban({
        player_id: playerToBan.player_id,
        reason: playerToBan.ban.reason,
        user_id: req.session.user.user_id,
        ban_datetime: moment().format(moment.application_dateformat),
        user_ip: req.connection.remoteAddress,
        is_lifted: false,
    }).save()
    .then(function(resp){
        if (resp != null) {
            new Database.Models.Player({player_id : playerToBan.player_id})
            .fetch({withRelated: ['bans']})
            .then(function(resp){
                callback(resp);
            });
        } else {
            callback(null);
        };
    });
};

PlayerController.postPlayerUnban = function(req, res) {
	log('postPlayerUnban: ' + req.originalUrl + ' : ' + util.inspect(req.body, { showHidden: true, depth: null }));
	if (req.body) {
        var isArray = (req.body instanceof Array);
		var unbanArray = [].concat( req.body );
		log('banArray: ' + util.inspect(unbanArray,false,null));
		var isValid = true;
		var unbanModels = [];
        var count = 0;
        var playerIds = [];
        if (unbanArray != null && unbanArray.length > 0) {
		    for (i = 0; i < unbanArray.length; i++) {
                unbanPlayer(unbanArray[i], req, function(player) {
                    count++;
                    if (player != null) {
                        unbanModels.push(player);
                    };
                    if (isArray) {
                        if (count == banArray.length) {
                            res.send(200,unbanModels);
                        };
                    } else {
                        if (player != null) {
                            res.send(200,player);
                        } else {
                            res.send(500,{ status: 500, type: 'Resource', message: 'Failed to reload unbanned player' });
                        };
                    };
                });
		    };
        };
	} else {
		res.send(500,{ status: 500, type: 'Resource', message: 'Argument not valid' });
	};	
};

unbanPlayer = function(player, req, callback) {
    var playerToUnBan = player;
    new Database.Collections.Bans()
	.query(function(qb) {
		qb.where('player_id', playerToUnBan.player_id).andWhere('is_lifted', '0');
	})
    .fetch()
    .then(function(resp){
        if (resp != null && resp.length > 0) {
            for(var i=0; i < resp.length; i++){
                var ban = resp.at(i);
                ban.set({
                    is_lifted : true,
                    user_lift_id : req.session.user.user_id,
                    user_lift_ip : req.connection.remoteAddress,
                    lifted_datetime: moment().format(moment.application_dateformat),
                }).save();
            };
            new Database.Models.Player({player_id : playerToUnBan.player_id})
            .fetch({withRelated: ['bans']})
            .then(function(resp){
                callback(resp);
            });
        } else {
            callback(null);
        };
    });
};

PlayerController.postPlayer = function(req, res) {
	log('postPlayer: ' + req.originalUrl + ' : ' + util.inspect(req.body, { showHidden: true, depth: null }));
    if (req.session.user.role < Router.Owner) {
        res.send(401,null);
    } else {
	    if (req.body) {
		    if (req.body.guid && req.body.guid.length <= 0) {
                req.body.guid = null;
			    delete req.body.guid;
		    };
		    if (req.body.gameid != null && req.body.gameid.length <= 0) {
                req.body.gameid = null;
			    delete req.body.gameid;
		    };
		    if (req.body.player_id && req.body.player_id <= 0) {
                req.body.player_id = null;
			    delete req.body.player_id;
		    };
		    if (!req.body.guid) {
			    res.send(500,null);
		    } else {
                if (req.body.player_name) {
                    req.body.player_name = req.body.player_name.toLowerCase();
                };
                req.body.last_datetime = moment().format(moment.application_dateformat);
                new Database.Collections.Players()
		            .query(function(qb) {
			            qb.where('guid', req.body.guid); //.andWhere('is_active', '!=', '0');
		            })
                    .fetch()
                    .then(function(resp) {
                        if (resp != null && resp.length > 0) {
                            var player = resp.at(0);
                            // Existing user, we load it and update it
                            req.body.connection_count = (player.get('connection_count') || 1) + 1;
                            player.set(req.body);
                            player
			                    .save()
                                .then(function(resp) {
                                    if (resp != null) {
                                        new Database.Models.PlayerHistory({
                                            player_id: resp.get('player_id'),
                                            server_id: resp.get('last_server'),
                                            player_name: resp.get('player_name'),
                                            connect_datetime: resp.get('last_datetime'),
                                            ip: resp.get('last_ip'),
                                        }).save();
					                    res.json(200, resp);
					                    log('replied: ' + util.inspect(resp, false, null));
                                    } else {
                                        res.send(500,{ status: 500, type: 'Resource', message: 'Error updating the player' });
                                    };
                                });
                        } else {
                            // New user directly saved to the DB
                            req.body.connection_count = 0;
                            new Database.Models.Player(req.body)
				                .save()
				                .then(function(resp) {
                                    if (resp != null) {
                                        new Database.Models.PlayerHistory({
                                            player_id: resp.get('player_id'),
                                            server_id: resp.get('last_server'),
                                            player_name: resp.get('player_name'),
                                            connect_datetime: resp.get('last_datetime'),
                                            ip: resp.get('last_ip'),
                                        }).save();
					                    res.json(200, resp);
					                    log('replied: ' + util.inspect(resp, false, null));
                                    } else {
                                        res.send(500,{ status: 500, type: 'Resource', message: 'Error saving the player' });
                                    };
				                });
                        };
                    });
		    };
	    } else {
		    res.send(500,{ status: 500, type: 'Resource', message: 'Argument not valid' });
	    };
    };
};